﻿using System;
using MockCommon;
using MockDataAccess;
using MockDataTransferObject;
using System.Data;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace MockBusiness
{
    public class ConsultantBusiness
    {
        #region Initialize
        private static ConsultantBusiness _instance;
        private readonly ConsultantDataAccess _consultantDataAccess;
        private readonly RoleDataAccess _roleDataAccess;
        private readonly UserDataAccess _userDataAccess;

        /// <summary>
        /// Gets the consultant data test.
        /// </summary>
        public Collection<Consultant> ConsultantDataTest
        {
            get
            {
                return _consultantDataAccess.AffectedRows;
            }
        }

        /// <summary>
        /// Gets the role data test.
        /// </summary>
        public Collection<Role> RoleDataTest
        {
            get
            {
                return _roleDataAccess.AffectedRows;
            }
        }

        /// <summary>
        /// Gets the user data test.
        /// </summary>
        public Collection<User> UserDataTest
        {
            get
            {
                return _userDataAccess.AffectedRows;
            }
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="ConsultantBusiness"/> class from being created.
        /// </summary>
        private ConsultantBusiness()
        {
            _consultantDataAccess = new ConsultantDataAccess();
            _roleDataAccess = new RoleDataAccess();
            _userDataAccess = new UserDataAccess();
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="ConsultantBusiness"/> class from being created.
        /// </summary>
        /// <param name="isFake">if set to <c>true</c> [is fake].</param>
        private ConsultantBusiness(bool isFake)
        {
            _consultantDataAccess = new ConsultantDataAccess(isFake);
            _roleDataAccess = new RoleDataAccess(isFake);
            _userDataAccess = new UserDataAccess(isFake);
        }

        /// <summary>
        /// Retrieves the instance.
        /// </summary>
        /// <returns></returns>
        public static ConsultantBusiness RetrieveInstance()
        {
            if (_instance == null)
                _instance = new ConsultantBusiness();
            return _instance;
        }

        /// <summary>
        /// Retrieves the instance.
        /// </summary>
        /// <param name="isFake">if set to <c>true</c> [is fake].</param>
        /// <returns></returns>
        public static ConsultantBusiness RetrieveInstance(bool isFake)
        {
            if (_instance == null)
                _instance = new ConsultantBusiness(isFake);
            return _instance;
        }
        #endregion

        #region CUD
        /// <summary>
        /// Inserts the specified consultant.
        /// </summary>
        /// <param name="consultant">The consultant.</param>
        public void Insert(Consultant consultant)
        {
            if (consultant == null)
            {
                throw new MockException("Consultant is null", "Business");
            }
            //Check ConsultantId.
            if (_consultantDataAccess.Exist(consultant.ConsultantId))
            {
                throw new MockException("ClientId was existed", "Business");
            }
            //Check RoleId
            Role role = consultant.User.Role;
            if (!_roleDataAccess.Exist(role.RoleId))
            {
                throw new MockException("Role is not exist", "Business");
            }
            //Check UserId
            User user = consultant.User;
            if (_userDataAccess.Exist(user.UserId))
            {
                throw new MockException("User is exist", "Business");
            }
            //Check username.
            if (_userDataAccess.IsExistUserName(user.UserName))
            {
                throw new MockException("username is exist", "Business");
            }
            //Check First name
            if (String.IsNullOrEmpty(consultant.FirstName))
            {
                throw new MockException("First name is not valid", "Business");
            }
            //Check Last name.
            string lastName = consultant.LastName;
            lastName = lastName.Trim();
            if (String.IsNullOrEmpty(consultant.LastName) || lastName.IndexOf(" ", StringComparison.CurrentCulture) != -1)
            {
                throw new MockException("Last name is not valid", "Business");
            }
            //Insert into database.
            _consultantDataAccess.Create(consultant, true);
        }

        /// <summary>
        /// Deletes the specified consultant id.
        /// </summary>
        /// <param name="consultantId">The consultant id.</param>
        public void Delete(string consultantId)
        {
            if (consultantId == null)
            {
                throw new MockException("Consultant is null", "Business");
            }
            if( !_consultantDataAccess.Exist(consultantId))
            {
                throw new MockException("ConsultantId is not exist", "Business");
            }
            int count = GetCountManagementContract(consultantId);
            if (count > 0)
            {
                throw new MockException("You can not delete the consultant because it's consulting " + count + " contracts.", "Business");
            }           
            _consultantDataAccess.Delete(consultantId);
        }

        /// <summary>
        /// Updates the specified consultant.
        /// </summary>
        /// <param name="consultant">The consultant.</param>
        public void Update(Consultant consultant)
        {
            if (consultant == null)
            {
                throw new MockException("Consultant is null", "Business.Update");
            }
            //Check ConsultantId.
            if ( !_consultantDataAccess.Exist(consultant.ConsultantId))
            {
                throw new MockException("ConsultantId is not exist", "Business.Update");
            }
            //Check RoleId
            Role role = consultant.User.Role;
            if (!_roleDataAccess.Exist(role.RoleId))
            {
                throw new MockException("Role is not exist", "Business.Update");
            }
            //Check First name
            if (String.IsNullOrEmpty(consultant.FirstName))
            {
                throw new MockException("First name is not valid", "Business.Update");
            }
            //Check Last name.
            string lastName = consultant.LastName;
            lastName = lastName.Trim();
            if (String.IsNullOrEmpty(consultant.LastName) || lastName.IndexOf(" ", StringComparison.CurrentCulture) != -1)
            {
                throw new MockException("Last name is not valid", "Business.Update");
            }
            _consultantDataAccess.Update(consultant, true);  
        }

        #endregion

        #region R
        /// <summary>
        /// Retrieves all consultants.
        /// </summary>
        /// <returns></returns>
        public Collection<Consultant> RetrieveAllConsultants()
        {
            return _consultantDataAccess.RetrieveAllConsultants();
        }

        /// <summary>
        /// Retrieves all consultant users.
        /// </summary>
        /// <returns></returns>
        public DataTable RetrieveAllConsultantUsers()
        {
            return _consultantDataAccess.RetrieveAllConsultantUsers();
        }

        /// <summary>
        /// Gets the name of the consultant id by user.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <returns></returns>
        public object GetConsultantIdByUserName(string userName)
        {
            if (userName == null)
                return null;
            return _consultantDataAccess.GetConsultantIdByConsultantUserName(userName);
        }

        /// <summary>
        /// Gets the name of the by user.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <returns></returns>
        public Consultant GetByUserName(string userName)
        {
            return _consultantDataAccess.GetByUserName(userName);
        }

        /// <summary>
        /// Gets the by id.
        /// </summary>
        /// <param name="consultantId">The consultant id.</param>
        /// <returns></returns>
        public Consultant GetById(object consultantId)
        {
            return _consultantDataAccess.GetById(consultantId);
        }

        /// <summary>
        /// Gets the count management contract.
        /// </summary>
        /// <param name="consultantId">The consultant id.</param>
        /// <returns></returns>
        public int GetCountManagementContract(string consultantId)
        {
            if (consultantId == null)
            {
                throw new MockException("ConsultantId is null.", "Business");
            }
            if (!_consultantDataAccess.Exist(consultantId))
            {
                throw new MockException("ConsultantId is not exist.", "Business");
            }
            return (int)_consultantDataAccess.GetCountManagementContract(consultantId);
        }

        /// <summary>
        /// Gets the consultants by filter.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="email">The email.</param>
        /// <param name="firstName">The first name.</param>
        /// <param name="lastName">The last name.</param>
        /// <param name="isActive">The is active.</param>
        /// <returns></returns>
        public Collection<Consultant> GetConsultantsByFilter(object userName, object email, object firstName, object lastName, object isActive)
        {
            return _consultantDataAccess.GetByFilter(userName, email, firstName, lastName, isActive);
        }
        #endregion
    }
}

